#include "x_timer.h"

XX_STATIC_IMP(xTimer)

xTimer::xTimer()
{
	thread_create();
}


xTimer::~xTimer()
{
	thread_signal();
	thread_join();

	std::map<uint64, Timer*>::iterator begin = timer_list_.begin();
	for (; begin != timer_list_.end(); ++begin){
		delete begin->second;
	}
	timer_list_.clear();
}

void xTimer::CancelTimer(uint64 timeid)
{
	std::map<uint64, Timer*>::iterator iter;

	thread_enter();

	iter = timer_list_.find(timeid);
	if (iter != timer_list_.end()) {
		delete iter->second;
		timer_list_.erase(iter);
	}

	thread_leave();
}

uint64 xTimer::RegisterTimer(tmCallBack cb, void* user, unsigned int timerInterval, int repeat)
{
	Timer* timer = new Timer();
	timer->user = user;
	timer->on_timer = cb;
	timer->repeat = repeat;

	timer->timerInterval = timerInterval;
	timer->timerlastrun = GetCurMs() + timerInterval;

	timer_list_[(uint64)timer] = timer;

	return (uint64)timer;
}

void  xTimer::Run()
{
	std::map<uint64, Timer*>::iterator iter;
	while (!thread_timewait(1000)){

		thread_enter();

		iter = timer_list_.begin();
		unsigned int cur_time = GetCurMs();
		for (; iter != timer_list_.end(); iter++) {

			Timer* cur_timer = iter->second;

			if (cur_timer->timerlastrun <= cur_time) {

				if (-1 != cur_timer->repeat) {
					if (cur_timer->repeat == 0) {
						delete cur_timer;
						continue;
					}
					cur_timer->repeat --;
				}

				cur_timer->on_timer(cur_timer->user);
				cur_timer->timerlastrun = cur_timer->timerInterval + cur_time;
			}
		}
		thread_leave();
	}
}

unsigned int GetCurMs()
{
#ifdef _WIN32
	return GetTickCount();
#else
	struct timeval tv;
	struct timezone tz;
	gettimeofday(&tv, &tz);

	return ((tv.tv_usec / 1000) + tv.tv_sec * 1000);
#endif
}